package com.restaurantpicker.util;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;

import org.apache.commons.lang.StringEscapeUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.util.Log;

import com.restaurantpicker.model.Place;

/**
 * @author saxman
 */
public class GooglePlacesApiService {
    private static final String LOG_TAG = "GooglePlacesApiService";

    //https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=40.417923,-3.709565&rankby=distance&types=restaurant&keyword=sushi&sensor=false&key=AIzaSyBbew32IyIjmhVtRqOuw1VDVeESwyJUMjk
    //https://maps.googleapis.com/maps/api/place/details/json?key=AIzaSyBbew32IyIjmhVtRqOuw1VDVeESwyJUMjk&sensor=true&reference=CoQBewAAANL-MR5bh-ZOxBkcyH57Yfy_-DYgdq1TfFvPQHuVQHY1kxxzXnYCnUpa9M0pmXLY7FGqF_wSnMFfAiRa6cZrQH1ZrY4U4wTVZW9gd1OgufTXXGj1wpOgKBHDRl2Y8CT64pM10ShPOJv5EM6wXZesJMDRDogBGgXtLDOdHaCpk4TIEhAZQVG7bUrq6i0uYWuAyL9KGhQhHmoh4sf_6y6wIfhEJrLCsjA2iQ
    //http://maps.googleapis.com/maps/api/distancematrix/json?sensor=false&origins=40.417923,-3.709565&destinations=40.4190170,-3.707730
    //https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&key=AIzaSyBbew32IyIjmhVtRqOuw1VDVeESwyJUMjk&sensor=true&photoreference=CnRlAAAAKapEc6S6Fb8GauOKl1Vl47E7AW_CdTR3RWDSlXGrBJEMXsEOB70F0KiwoObcykkr-9xlv5ms9aWq2qug7VwH5bm6npZc67DSJV_-Mk9d4CYkvnla77FgnvhstjM2zO3EbJVIUPM5-63Nc-gZGSEXXBIQgLUPNyMqp4CSMblXc5U84BoUGayjv_t3LcXOXNKPnfpmZfMEGzI
    private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
    private static final String PLACES_API_DISTANCE = "http://maps.googleapis.com/maps/api/distancematrix";
    //private static final String PLACES_API_PHOTO = "https://maps.googleapis.com/maps/api/place/photo";
    private static final String TYPE_NEARBY = "/nearbysearch";
    private static final String OUT_JSON = "/json";

    // KEY!
    private static final String API_KEY = "AIzaSyBbew32IyIjmhVtRqOuw1VDVeESwyJUMjk";
    
    Context mContext;

    public GooglePlacesApiService(Context m){
    	mContext = m;
    }

    public ArrayList<Place> search(String keyword, double lat, double lng, int radius) {
        ArrayList<Place> resultList = new ArrayList<Place>();

        HttpURLConnection conn = null;
        StringBuilder jsonResults = new StringBuilder();
        try {
            StringBuilder sb = new StringBuilder(PLACES_API_BASE);
            sb.append(TYPE_NEARBY);
            sb.append(OUT_JSON);
            sb.append("?sensor=false");
            sb.append("&key=" + API_KEY);
            sb.append("&types=restaurant");
            sb.append("&rankby=distance");//sb.append("&radius=" + String.valueOf(radius));
            
            if(keyword !=null && !keyword.equals("any"))
            	sb.append("&keyword=" + URLEncoder.encode(keyword, "utf8"));
            
            sb.append("&location=" + String.valueOf(lat) + "," + String.valueOf(lng));

            URL url = new URL(sb.toString());
            conn = (HttpURLConnection) url.openConnection();
            InputStreamReader in = new InputStreamReader(conn.getInputStream());

            int read;
            char[] buff = new char[1024];
            while ((read = in.read(buff)) != -1) {
                jsonResults.append(buff, 0, read);
            }
        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "Error processing Places API URL", e);
            return resultList;
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error connecting to Places API", e);
            return resultList;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }

        try {
            // Create a JSON object hierarchy from the results
            JSONObject jsonObj = new JSONObject(jsonResults.toString());
            JSONArray predsJsonArray = jsonObj.getJSONArray("results");
            JSONArray predsJsonPhotosArray;

            // Extract the Place descriptions from the results
            resultList = new ArrayList<Place>(predsJsonArray.length());
            for (int i = 0; i < predsJsonArray.length(); i++) {
            	Place place = new Place();
            	place.id = predsJsonArray.getJSONObject(i).getString("id");
            	place.reference = predsJsonArray.getJSONObject(i).getString("reference");
                place.name = StringEscapeUtils.escapeHtml(predsJsonArray.getJSONObject(i).getString("name")).replace("'", "&prime;");
                place.formatted_address = StringEscapeUtils.escapeHtml(predsJsonArray.getJSONObject(i).getString("vicinity")).replace("'", "&prime;");
                place.rating = (predsJsonArray.getJSONObject(i).has("rating")) ? predsJsonArray.getJSONObject(i).getString("rating") : "0";
                place.longitude = predsJsonArray.getJSONObject(i).getJSONObject("geometry").getJSONObject("location").getString("lng");
                place.latitude = predsJsonArray.getJSONObject(i).getJSONObject("geometry").getJSONObject("location").getString("lat");
                predsJsonPhotosArray = (predsJsonArray.getJSONObject(i).has("photos")) ? predsJsonArray.getJSONObject(i).getJSONArray("photos") : new JSONArray();
                for (int j = 0; j < predsJsonPhotosArray.length(); j++) {
                	place.photo_reference = predsJsonPhotosArray.getJSONObject(j).getString("photo_reference");	
                }
                place.distance = getDistance(String.valueOf(lat), String.valueOf(lng), place.latitude, place.longitude);
                place.open = (predsJsonArray.getJSONObject(i).has("opening_hours") && predsJsonArray.getJSONObject(i).getJSONObject("opening_hours").has("open_now") && predsJsonArray.getJSONObject(i).getJSONObject("opening_hours").getString("open_now").equals("true")) ? "open" : "closed";
                resultList.add(place);
            }
        } catch (JSONException e) {
            Log.e(LOG_TAG, "Error processing JSON results", e);
        }

        return resultList;
    }
    
    public String getDistance(String lat, String lng, String destLat, String destLng) {
    	String distance = null;
    	
    	HttpURLConnection conn = null;
        StringBuilder jsonResults = new StringBuilder();
        try {
            StringBuilder sb = new StringBuilder(PLACES_API_DISTANCE);
            sb.append(OUT_JSON);
            sb.append("?sensor=false");
            sb.append("&origins=" + lat + "," + lng);
            sb.append("&destinations=" + destLat + "," + destLng);

            URL url = new URL(sb.toString());
            conn = (HttpURLConnection) url.openConnection();
            InputStreamReader in = new InputStreamReader(conn.getInputStream());

            int read;
            char[] buff = new char[1024];
            while ((read = in.read(buff)) != -1) {
                jsonResults.append(buff, 0, read);
            }
        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "Error processing Places API URL", e);
            return distance;
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error connecting to Places API", e);
            return distance;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }

        try {
            // Create a JSON object hierarchy from the results
            JSONObject jsonObj = new JSONObject(jsonResults.toString());
            JSONArray predsJsonArray = jsonObj.getJSONArray("rows");
            JSONArray predsDistJsonArray;

            // Extract the Place descriptions from the results
            for (int i = 0; i < predsJsonArray.length(); i++) {
            	predsDistJsonArray = (predsJsonArray.getJSONObject(i).has("elements")) ? predsJsonArray.getJSONObject(i).getJSONArray("elements") : new JSONArray();
            	for (int j = 0; j < predsDistJsonArray.length(); j++){
            		distance = predsDistJsonArray.getJSONObject(j).getJSONObject("distance").getString("text");            		
            	}            	
            }
        } catch (JSONException e) {
            Log.e(LOG_TAG, "Error processing JSON results", e);
        }

        return distance;
    }  
    
    public String getPhone(String reference) {
    	String phone = "Can't find phone number";
    	
    	HttpURLConnection conn = null;
        StringBuilder jsonResults = new StringBuilder();
        try {
            StringBuilder sb = new StringBuilder(PLACES_API_BASE);
            sb.append("/details");
            sb.append(OUT_JSON);
            sb.append("?sensor=false");
            sb.append("&key=" + API_KEY);
            sb.append("&reference=" + reference);

            URL url = new URL(sb.toString());
            conn = (HttpURLConnection) url.openConnection();
            InputStreamReader in = new InputStreamReader(conn.getInputStream());

            int read;
            char[] buff = new char[4*1024];
            while ((read = in.read(buff)) != -1) {
                jsonResults.append(buff, 0, read);
            }
        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "Error processing Places API URL", e);
            return phone;
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error connecting to Places API", e);
            return phone;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }

        try {
            // Create a JSON object hierarchy from the results
            JSONObject jsonObj = new JSONObject(jsonResults.toString());
            
            phone = jsonObj.getJSONObject("result").getString("formatted_phone_number");
           
        } catch (JSONException e) {
            Log.e(LOG_TAG, "Error processing JSON results", e);
        }

        return phone;
    }    
}
